﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Abp.Domain.Entities;
using Abp.Domain.Entities.Auditing;
using Abp.Timing;
using Abp.UI;
using DHJ.Cost.CostBooking.Event;
using DHJ.Cost.Timing;
using DHJ.Cost.Workshops;
using JetBrains.Annotations;

namespace DHJ.Cost.CostBooking
{
    public class ActualCost : AuditedAggregateRoot<Guid>, IExtendableObject
    {
        public ActualCost()
        {
        }

        public ActualCost(OccurrenceTime time,
            CostSubject subject,
            CostDetail detail,
            Workshop? workshop = null,
            string modelId = null,
            string taskId = null)
        {
            Time = time;
            Subject = subject;
            Detail = detail;
            Workshop = workshop;
            ModelId = modelId;
            TaskId = taskId;
        }

        [Required] public OccurrenceTime Time { get; private set; }

        [Required] public CostSubject Subject { get; private set; }

        [Required] public CostDetail Detail { get; private set; }

        [CanBeNull] public Workshop? Workshop { get; private set; }

        [CanBeNull] public string ModelId { get; private set; }

        [CanBeNull] public string TaskId { get; private set; }

        public string Remarks { get; set; }

        public bool IsCredited { get; private set; }
        public DateTime? CreditTime { get; private set; }

        public bool IsAccounted { get; private set; }
        public DateTime? AccountTime { get; private set; }

        public string ExtensionData { get; set; }


        public virtual void Credit()
        {
            if (IsCredited)
                throw new ApplicationException("此项成本已入账");

            IsCredited = true;
            CreditTime = Clock.Now;
        }

        public void Account(IBatchRatioCalculationContext context)
        {
            if (IsAccounted)
                throw new ApplicationException("此项成本已核算");

            //计算与该成本相关的任务及所占比例
            var ratios = CalculateBatchRatios(context);
            DomainEvents.Add(new CostAccounted
            {
                Cost = this,
                Ratios = ratios
            });

            IsAccounted = true;
            AccountTime = Clock.Now;
        }

        protected virtual List<BatchRatio> CalculateBatchRatios(IBatchRatioCalculationContext context)
        {
            var manHours = context.ManHourManager.GetManHours(Time, Workshop, ModelId, TaskId, false);
            if (!manHours.Any()) throw new UserFriendlyException("没有可以均摊的工时任务!");

            var total = manHours.Sum(mh => mh.Hours.Standard);
            return manHours.Select(mh => new BatchRatio
            {
                BatchId = mh.BatchId,
                Quantity = mh.Quantity,
                Workshop = mh.Workshop,
                Ratio = mh.Hours.Standard / total
            }).ToList();
        }
    }
}